<?php
/**
 * Created by PhpStorm.
 * User: Sky
 * Date: 2017/7/27
 * Time: 上午11:34
 */

namespace app\librarys;

use app\models\SqlOperateLog;

class DbCacheUtility
{
    const DefaultTime = 0;
    const NoCacheTime = 0;
    const LowCacheTime = 60 * 1;
    const NormalCacheTime = 60 * 10;
    const HighCacheTime = 60 * 60;

    /**
     * @param \Yii\db\Command $cmd
     * @param int $cacheDuration 缓存时间. 如果为0,则重新从数据库取数据.
     * @return mixed
     */
    public static function queryAll($cmd, $cacheDuration = self::DefaultTime, $is_log = true)
    {
        $begin_time = Tools::getMillisecond();

        $is_cache = 0;

        $md5_name = md5($cmd->sql);


        $key = 'query_all:' . md5($cmd->getRawSql());

        if ($cacheDuration == 0) {
            if (\Yii::$app->cache->exists($key)) {
                \Yii::$app->cache->delete($key);
            }
        }

        if (!(\Yii::$app->cache->exists($key))) {
            $result = $cmd->queryAll();
            if ($cacheDuration != 0) {
                \Yii::$app->cache->set($key, $result, $cacheDuration);
            }
        } else {
            $is_cache = 1;
            $result = \Yii::$app->cache->get($key);
        }


        $end_time = Tools::getMillisecond();
        self::saveSqlLog($md5_name, 'query_all', $begin_time, $end_time, $cmd, $is_cache, $is_log);

        return $result;
    }

    /**
     * @param \Yii\db\Command $cmd
     * @param int $cacheDuration 缓存时间. 如果为0,则重新从数据库取数据.
     * @return mixed
     */
    public static function queryOne($cmd, $cacheDuration = self::DefaultTime, $is_log = true)
    {
        $begin_time = Tools::getMillisecond();
        $is_cache = 0;
        $md5_name = md5($cmd->sql);

        $key = 'query_one:' . md5($cmd->getRawSql());
        if ($cacheDuration == 0) {
            if (\Yii::$app->cache->exists($key)) {
                \Yii::$app->cache->delete($key);
            }
        }

        if (!(\Yii::$app->cache->exists($key))) {
            $result = $cmd->queryOne();
            if ($cacheDuration != 0) {
                \Yii::$app->cache->set($key, $result, $cacheDuration);
            }
        } else {
            $is_cache = 1;
            $result = \Yii::$app->cache->get($key);
        }

        $end_time = Tools::getMillisecond();
        self::saveSqlLog($md5_name, 'query_one', $begin_time, $end_time, $cmd, $is_cache, $is_log);

        if (!$result) {
            return null;
        }

        return $result;
    }

    /**
     * @param \Yii\db\Command $cmd
     * @param int $cacheDuration 缓存时间. 如果为0,则重新从数据库取数据.
     * @return mixed
     */
    public static function queryScalar($cmd, $cacheDuration = self::DefaultTime, $is_log = true)
    {
        $begin_time = Tools::getMillisecond();
        $is_cache = 0;
        $md5_name = md5($cmd->sql);
        $key = 'query_scalar:' . md5($cmd->getRawSql());

        if ($cacheDuration == 0) {
            if (\Yii::$app->cache->exists($key)) {
                \Yii::$app->cache->delete($key);
            }
        }

        if (!(\Yii::$app->cache->exists($key))) {

            $result = $cmd->queryScalar();
            if ($cacheDuration != 0) {
                \Yii::$app->cache->set($key, $result, $cacheDuration);
            }
        } else {
            $is_cache = 1;
            $result = \Yii::$app->cache->get($key);
        }

        $end_time = Tools::getMillisecond();
        self::saveSqlLog($md5_name, 'query_scalar', $begin_time, $end_time, $cmd, $is_cache, $is_log);

        return $result;
    }

    /**
     * @param \Yii\db\Command $cmd
     * @return int
     */
    public static function execute($cmd, $is_log = true)
    {
        $begin_time = Tools::getMillisecond();

        $md5_name = md5($cmd->sql);
        $result = $cmd->execute();

        $end_time = Tools::getMillisecond();
        self::saveSqlLog($md5_name, 'execute', $begin_time, $end_time, $cmd, 0, $is_log);
        return $result;
    }


    /**
     * 保存sql日志
     * @param $md5_name
     * @param $type
     * @param $begin_time
     * @param $end_time
     * @param $cmd
     * @param $is_cache
     * @param bool $is_log
     */
    public static function saveSqlLog($md5_name, $type, $begin_time, $end_time, $cmd, $is_cache, $is_log = true)
    {
        if ($is_log) {
            $is_sql_log = \Yii::$app->params['is_sql_log'];
            if ($is_sql_log == true) {
                try {
                    $controllerId = \Yii::$app->controller->id;
                    $actionId = \Yii::$app->requestedAction->id;
                    SqlOperateLog::add($controllerId, $actionId, $md5_name, $type, $end_time - $begin_time, $cmd, $is_cache);
                } catch (\Exception $ex) {
                }
            }
        }
    }

}